home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 008a / fgdemo10.zip / EDITOR.C < prev    next >
Text File  |  1991-10-05  |  29KB  |  1,009 lines

  1. /**********************************************************************\
  2. *                                                                      *
  3. *  editor.c -- this is a primitive graphics mode editor with word-wrap *
  4. *  It can be used as a template for a graphics mode editor, but it is  *
  5. *  not certified bug-free, and anybody thinking of using this code     *
  6. *  should study it carefully, beta-test it thoroughly, and debug as    *
  7. *  appropriate.  This code is presented here primarily for academic    *
  8. *  purposes: it is one approach to the problem of how to write a       *
  9. *  graphics mode text editor.                                          *
  10. *                                                                      *
  11. *  Use this code freely, and send suggestions for optimizations and    *
  12. *  improvements to Diana Gruber.                                       *
  13. *                                                                      *
  14. \**********************************************************************/
  15.  
  16. #include "defs.h"
  17.  
  18. #define CTRL_Y      25
  19.  
  20. #define F1          59
  21. #define F2          60
  22. #define F9          67
  23. #define F10         68
  24.  
  25. #define CHAR_WIDTH   8
  26.  
  27. int overstrike;
  28. int top_row, bottom_row;
  29.  
  30. /**********************************************************************\
  31. *                                                                      *
  32. *  can_wrap -- is there enough room to do a word wrap?                 *
  33. *                                                                      *
  34. \**********************************************************************/
  35.  
  36. can_wrap(s1,s2,length)
  37. char *s1, *s2;
  38. int length;
  39. {
  40.    if (strlen(s1)+strlen(s2) < length)
  41.       return(TRUE);
  42.    else
  43.       return(FALSE);
  44. }
  45.  
  46. /**********************************************************************\
  47. *                                                                      *
  48. *  clear_string -- clear all or part of a row of chars                 *
  49. *                                                                      *
  50. \**********************************************************************/
  51.  
  52. void clear_string(x,y,len,maxx)
  53. int x, y, len, maxx;
  54. {
  55.    int x1, y0;
  56.    int color;
  57.  
  58.    if (len == 0) return;
  59.  
  60.    y0 = y - ptsize;
  61.    x1 = x + len * CHAR_WIDTH - 1;
  62.    if (x1 > maxx) x1 = maxx;
  63.  
  64.    color = fg_getcolor();
  65.    fg_setcolor(background);
  66.    fg_rect(x,x1,y0,y);
  67.    fg_setcolor(color);
  68. }
  69.  
  70. /**********************************************************************\
  71. *                                                                      *
  72. *  editor -- edit nrows lines of text                                  *
  73. *                                                                      *
  74. \**********************************************************************/
  75.  
  76. editor(array,minx,maxx,miny,maxy,nrows,array_len)
  77. char *array;
  78. int  minx, miny, maxx, maxy, nrows;
  79. int  *array_len;
  80. {
  81.    register int i, n;
  82.    int b, l;
  83.    int x, y;
  84.    int iy;
  85.    unsigned char key, aux;
  86.    static char char_string[] = {0,0};
  87.    int maxcol;
  88.    int row;
  89.    char *tempstring;
  90.    char *string[101];
  91.    int col[101];
  92.    int end[101];
  93.    int color;
  94.    int visible_rows;
  95.  
  96.    color = fg_getcolor();
  97.    fg_setpage(visual);
  98.    overstrike = FALSE;
  99.    iy = miny + ptsize;
  100.  
  101.    /* determine the string size */
  102.  
  103.    maxcol = (maxx+1 - minx) / CHAR_WIDTH;
  104.  
  105.    /* allocate space for the strings and initialize all elements to 0 */
  106.  
  107.    for (n = 0; n < nrows; n++)
  108.    {
  109.       if ((string[n] = calloc(maxcol+3,sizeof(char))) == NULL)
  110.          return(ERR);
  111.       col[n] = 0;
  112.       end[n] = 0;
  113.    }
  114.  
  115.    tempstring = calloc(maxcol+2,sizeof(char));
  116.  
  117.    /* display whatever is in the array now */
  118.  
  119.    l = 0;
  120.    x = minx;
  121.    y = iy;
  122.    top_row = 0;
  123.    bottom_row = ((maxy - miny + 1) / (ptsize+1));
  124.    if (bottom_row > nrows) bottom_row = nrows;
  125.  
  126.    /* recalc maxy based on ptsize, for scrolling */
  127.  
  128.    maxy = iy + 1 + (bottom_row-1) * (ptsize + 1);
  129.  
  130.    /* recalc nrows because they don't seem to come out right? */
  131.  
  132.    nrows++;
  133.  
  134.    for (row = top_row; row < bottom_row; row++)
  135.    {
  136.       put_string(&array[l],x,y);
  137.       strcpy(string[row],&array[l]);     /* copy it to the temp string */
  138.       unblank(string[row]);
  139.  
  140.       l += strlen(&array[l]) + 1;
  141.       col[row] = strlen(string[row]);
  142.       y += ptsize + 1;
  143.    }
  144.  
  145.    /* if there any rows beyond the bottom row */
  146.  
  147.    for (row = bottom_row; row<nrows; row++)
  148.    {
  149.       strcpy(string[row],&array[l]);
  150.       l += strlen(&array[l]) + 1;
  151.       unblank(string[row]);
  152.       col[row] = strlen(string[row]);
  153.    }
  154.  
  155.    flushkey();
  156.  
  157.    row = 0;      /* starting position */
  158.    col[row] = 0;
  159.    x = get_x(minx,col[row]);
  160.    y = iy;
  161.    put_editor_cursor(x,y);
  162.  
  163.    visible_rows = bottom_row - top_row;
  164.  
  165.    while (TRUE)
  166.    {
  167.       fg_getkey(&key,&aux);
  168.  
  169.       /* return */
  170.  
  171.       if (key == CR)
  172.       {
  173.          unblank(string[row]);
  174.          remove_editor_cursor(x,y);
  175.          if (row < bottom_row - 1)
  176.          {
  177.             n = end_paragraph(row,string);
  178.             if (n < bottom_row - 1)
  179.             {
  180.                for (i = n; i > row; i--)
  181.                {
  182.                   strcpy(string[i+1],string[i]);
  183.                   y = get_y(iy,i+1);
  184.                   clear_string(minx,y,maxcol,maxx);
  185.                   put_string(string[i+1],minx,y);
  186.                }
  187.                strcpy(string[row+1],&string[row][col[row]]);
  188.                string[row][col[row]] = NULL;
  189.                x = get_x(minx,col[row]);
  190.                y = get_y(iy,row);
  191.                clear_string(x,y,maxcol,maxx);
  192.                y = get_y(iy,row+1);
  193.                clear_string(minx,y,maxcol,maxx);
  194.                put_string(string[row+1],minx,y);
  195.             }
  196.             row++;
  197.          }
  198.          else if (bottom_row < nrows - 1)
  199.          {
  200.             fg_setcolor(background);
  201.             fg_scroll(minx,maxx,(iy+1),maxy,-(ptsize+1),1);
  202.             fg_setcolor(color);
  203.             bottom_row++;
  204.             top_row++;
  205.             row++;
  206.             y = get_y(iy,bottom_row-1);
  207.             put_string(string[bottom_row-1],minx,y);
  208.          }
  209.          else
  210.             row = top_row;
  211.  
  212.          col[row] = 0;
  213.          x = get_x(minx,col[row]);
  214.          y = get_y(iy,row);
  215.          put_editor_cursor(x,y);
  216.       }
  217.  
  218.       /* F1 -- help screen */
  219.  
  220.       else if (aux == F1)
  221.       {
  222.          remove_editor_cursor(x,y);
  223.          help_screen();
  224.          fg_setcolor(15);
  225.          put_editor_cursor(x,y);
  226.       }
  227.  
  228.       /* back space */
  229.  
  230.       else if (key == BS && col[row] > 0)
  231.       {
  232.          remove_editor_cursor(x,y);
  233.          col[row]--;
  234.          string[row][col[row]] = NULL; /* remove a character */
  235.  
  236.          strcpy(tempstring,string[row]);
  237.          strcat(tempstring,&string[row][col[row]+1]);
  238.          strcpy(string[row],tempstring);
  239.  
  240.          x = get_x(minx,col[row]);
  241.          clear_string(x,y,maxcol,maxx);
  242.          put_string(&string[row][col[row]],x,y);
  243.  
  244.          put_editor_cursor(x,y);
  245.       }
  246.  
  247.       /* delete */
  248.  
  249.       else if (aux == DELETE)
  250.       {
  251.          if (string[row][col[row]] == NULL && row < bottom_row-1)
  252.             /* delete at end of line */
  253.          {
  254.             end[row] = strlen(string[row]);
  255.             end[row+1] = strlen(string[row+1]);
  256.  
  257.             b = first_blank(string[row+1]);
  258.             if (end[row] + b <= maxcol)
  259.             {
  260.                remove_editor_cursor(x,y);
  261.  
  262.                /* see if you can wrap more than one word */
  263.  
  264.                while (end[row]+b <= maxcol && b < end[row+1])
  265.                {
  266.                   n = b;
  267.                   b += first_blank(&string[row+1][b+1]) + 1;
  268.                }
  269.                if (end[row]+b > maxcol) b = n;
  270.  
  271.                if (string[row+1][b] == NULL) /* wrap whole line */
  272.                {
  273.                   strcat(string[row],string[row+1]); /* move all lines up */
  274.  
  275.                   for (i = row+1; i < bottom_row; i++)
  276.                   {
  277.                      strcpy(string[i],string[i+1]);
  278.                      y = get_y(iy,i);
  279.                      clear_string(minx,y,maxcol,maxx);
  280.                      put_string(string[i],minx,y);
  281.                   }
  282.                   for (i = bottom_row; i < nrows-1; i++)
  283.                   {
  284.                      strcpy(string[i],string[i+1]);
  285.                   }
  286.                   string[nrows-1][0] = NULL;
  287.                }
  288.                else  /* wrap one word of several on next line */
  289.                {
  290.                   string[row+1][b] = NULL;
  291.                   strcat(string[row],string[row+1]);
  292.                   strcpy(tempstring,&string[row+1][b+1]);
  293.                   strcpy(string[row+1],tempstring);
  294.                   y = get_y(iy,row+1);
  295.                   clear_string(minx,y,maxcol,maxx);
  296.                   put_string(string[row+1],minx,y);
  297.                }
  298.                x = get_x(minx,col[row]);
  299.                y = get_y(iy,row);
  300.                put_string(&string[row][col[row]],x,y);
  301.                put_editor_cursor(x,y);
  302.             }
  303.             continue;
  304.          }
  305.          else if (string[row][col[row]] != NULL)
  306.          {
  307.             string[row][col[row]] = NULL; /* remove a character */
  308.  
  309.             strcpy(tempstring,string[row]);
  310.             strcat(tempstring,&string[row][col[row]+1]);
  311.             strcpy(string[row],tempstring);
  312.  
  313.             clear_string(x,y,maxcol,maxx);
  314.             put_string(&string[row][col[row]],x,y);
  315.          }
  316.       }
  317.  
  318.       /* line delete -- ctrl y */
  319.  
  320.       else if (key == CTRL_Y)
  321.       {
  322.          col[row] = 0;
  323.          string[row][col[row]] = NULL;
  324.          remove_editor_cursor(x,y);
  325.          x = minx;
  326.          clear_string(x,y,maxcol,maxx);
  327.          put_editor_cursor(x,y);
  328.       }
  329.  
  330.       /* left arrow */
  331.  
  332.       else if (aux == LEFT_ARROW)
  333.       {
  334.          if (col[row] > 0)
  335.          {
  336.             remove_editor_cursor(x,y);
  337.             col[row]--;
  338.             x = get_x(minx,col[row]);
  339.             put_editor_cursor(x,y);
  340.          }
  341.          else if (row > 0)
  342.          {
  343.             remove_editor_cursor(x,y);
  344.             row--;
  345.             end[row] = strlen(string[row]);
  346.             col[row] = MIN(end[row],maxcol-1);
  347.             x = get_x(minx,col[row]);
  348.             y = get_y(iy,row);
  349.             put_editor_cursor(x,y);
  350.          }
  351.       }
  352.  
  353.       /* right arrow */
  354.  
  355.       else if (aux == RIGHT_ARROW)
  356.       {
  357.          if (col[row] < maxcol-1)
  358.          {
  359.             if (string[row][col[row]] == NULL)
  360.             {
  361.                 string[row][col[row]] = 32;
  362.                 string[row][col[row]+1] = NULL;
  363.             }
  364.             remove_editor_cursor(x,y);
  365.             col[row]++;
  366.             x = get_x(minx,col[row]);
  367.             put_editor_cursor(x,y);
  368.          }
  369.          else if (row < bottom_row-1)
  370.          {
  371.             remove_editor_cursor(x,y);
  372.             row++;
  373.             col[row] = 0;
  374.             x = get_x(minx,col[row]);
  375.             y = get_y(iy,row);
  376.             put_editor_cursor(x,y);
  377.          }
  378.       }
  379.  
  380.       /* up arrow */
  381.  
  382.       else if (aux == UP_ARROW)
  383.       {
  384.          if (row > top_row)
  385.          {
  386.             unblank(string[row]);
  387.             remove_editor_cursor(x,y);
  388.             row--;
  389.             end[row] = strlen(string[row]);
  390.             col[row] = MIN(end[row],col[row+1]);
  391.             x = get_x(minx,col[row]);
  392.             y = get_y(iy,row);
  393.             put_editor_cursor(x,y);
  394.          }
  395.          else if (top_row > 0)
  396.          {
  397.             unblank(string[row]);
  398.             remove_editor_cursor(x,y);
  399.  
  400.             end[row] = strlen(string[row]);
  401.             col[row] = 0;
  402.  
  403.             bottom_row--;
  404.             top_row--;
  405.             row--;
  406.  
  407.             fg_setcolor(background);
  408.             fg_scroll(minx,maxx,miny-1,maxy-ptsize-3,ptsize+1,1);
  409.             fg_setcolor(color);
  410.  
  411.             x = get_x(minx,col[row]);
  412.             y = get_y(iy,row);
  413.             put_string(string[row],minx,y);
  414.             put_editor_cursor(x,y);
  415.          }
  416.       }
  417.  
  418.       /* down arrow */
  419.  
  420.       else if (aux == DOWN_ARROW)
  421.       {
  422.          if (row < bottom_row-1)
  423.          {
  424.             unblank(string[row]);
  425.             remove_editor_cursor(x,y);
  426.             row++;
  427.             end[row] = strlen(string[row]);
  428.             col[row] = MIN(end[row],col[row-1]);
  429.             x = get_x(minx,col[row]);
  430.             y = get_y(iy,row);
  431.             put_editor_cursor(x,y);
  432.          }
  433.          else if (bottom_row < nrows-1)
  434.          {
  435.             unblank(string[row]);
  436.             remove_editor_cursor(x,y);
  437.  
  438.             bottom_row++;
  439.             top_row++;
  440.             row++;
  441.  
  442.             end[row] = strlen(string[row]);
  443.             col[row] = MIN(end[row],col[row-1]);
  444.  
  445.             fg_setcolor(background);
  446.             fg_scroll(minx,maxx,iy+1,maxy,-(ptsize+1),1);
  447.             fg_setcolor(color);
  448.  
  449.             x = get_x(minx,col[row]);
  450.             y = get_y(iy,row);
  451.             put_string(string[row],minx,y);
  452.             put_editor_cursor(x,y);
  453.          }
  454.  
  455.       }
  456.  
  457.       /* PgUp */
  458.  
  459.       else if (aux == PAGE_UP && row > 0)
  460.       {
  461.          if (top_row > visible_rows)
  462.          {
  463.             top_row -= visible_rows;
  464.             bottom_row -= visible_rows;
  465.          }
  466.          else
  467.          {
  468.             top_row = 0;
  469.             bottom_row = visible_rows;
  470.          }
  471.  
  472.          fg_setcolor(background);
  473.          fg_rect(minx,maxx,miny,maxy);
  474.          fg_setcolor(color);
  475.  
  476.          for (row = top_row; row < bottom_row; row++)
  477.          {
  478.              y = get_y(iy,row);
  479.              put_string(string[row],minx,y);
  480.          }
  481.  
  482.          row = top_row;
  483.  
  484.          end[row] = strlen(string[row]);
  485.          col[row] = 0;
  486.          x = get_x(minx,col[row]);
  487.          y = get_y(iy,row);
  488.          put_editor_cursor(x,y);
  489.       }
  490.  
  491.       /* PgDn */
  492.  
  493.       else if (aux == PAGE_DOWN)
  494.       {
  495.          if (bottom_row < nrows-visible_rows)
  496.          {
  497.             top_row += visible_rows;
  498.             bottom_row += visible_rows;
  499.          }
  500.          else
  501.          {
  502.             top_row = nrows - visible_rows - 1;
  503.             bottom_row = nrows - 1;
  504.          }
  505.  
  506.          fg_setcolor(background);
  507.          fg_rect(minx,maxx,miny,maxy);
  508.          fg_setcolor(color);
  509.  
  510.          for (row = top_row; row < bottom_row; row++)
  511.          {
  512.              y = get_y(iy,row);
  513.              put_string(string[row],minx,y);
  514.          }
  515.  
  516.          row = top_row;
  517.  
  518.          end[row] = strlen(string[row]);
  519.          col[row] = 0;
  520.          x = get_x(minx,col[row]);
  521.          y = get_y(iy,row);
  522.          put_editor_cursor(x,y);
  523.       }
  524.  
  525.       /* home */
  526.  
  527.       else if (aux == HOME)
  528.       {
  529.          remove_editor_cursor(x,y);
  530.          col[row] = 0;
  531.          x = get_x(minx,col[row]);
  532.          y = get_y(iy,row);
  533.          put_editor_cursor(x,y);
  534.       }
  535.  
  536.       /* end */
  537.  
  538.       else if (aux == END)
  539.       {
  540.          remove_editor_cursor(x,y);
  541.          unblank(string[row]);
  542.          end[row] = strlen(string[row]);
  543.          col[row] = MIN(end[row],maxcol-1);
  544.          x = get_x(minx,col[row]);
  545.          y = get_y(iy,row);
  546.          put_editor_cursor(x,y);
  547.       }
  548.  
  549.       /* insert toggles insert mode */
  550.  
  551.       else if (aux == INSERT)
  552.       {
  553.          overstrike = !overstrike;
  554.          put_editor_cursor(x,y);
  555.       }
  556.       /* esc or F10 to return */
  557.  
  558.       else if (aux == F10 || key == ESC)
  559.          break;
  560.  
  561.       /* printable character -- insert mode */
  562.  
  563.       if ((is_char(key) || key == SPACEBAR) && !overstrike)
  564.       {
  565.          l = 0;
  566.          remove_editor_cursor(x,y);
  567.  
  568.          strcpy(tempstring,&string[row][col[row]]);
  569.          string[row][col[row]] = key;
  570.          string[row][col[row]+1] = NULL;
  571.          strcat(string[row],tempstring);
  572.          end[row] = strlen(string[row]);
  573.  
  574.          /* row too long, must wrap */
  575.  
  576.          if (end[row] > maxcol || col[row] == maxcol-1)
  577.          {
  578.             if (row == bottom_row-1 && bottom_row < nrows-1)
  579.             {
  580.                fg_setcolor(background);
  581.                fg_scroll(minx,maxx,iy+1,maxy,-(ptsize+1),1);
  582.                fg_setcolor(color);
  583.                bottom_row++;
  584.                top_row++;
  585.                y = get_y(iy,row+1);
  586.                put_string(string[row+1],minx,y);
  587.             }
  588.  
  589.             if (row < bottom_row-1)
  590.             {
  591.                b = last_blank(string[row]) + 1;
  592.                if (can_wrap(&string[row][b],string[row+1],maxcol))
  593.                {
  594.  
  595.                   l = b - col[row];
  596.                   word_wrap(&string[row][b],string[row+1]);
  597.                   string[row][b] = NULL;
  598.                   unblank(string[row]);
  599.                   unblank(string[row+1]);
  600.  
  601.                   /* redraw the second row of text */
  602.  
  603.                   y = get_y(iy,row+1);
  604.                   clear_string(minx,y,maxcol,maxx);
  605.                   put_string(string[row+1],minx,y);
  606.  
  607.                   /* recalc cursor position */
  608.  
  609.                   if (col[row] >= b) /* cursor is in word that gets wrapped */
  610.                   {
  611.                      /* erase last word of row */
  612.  
  613.                      x = get_x(minx,b);
  614.                      y = get_y(iy,row);
  615.                      clear_string(x,y,maxcol,maxx);
  616.  
  617.                      row++;
  618.                      col[row] = col[row-1] - b;
  619.                      unblank(string[row]);
  620.                   }
  621.                   else /* cursor stays on current line */
  622.                   {
  623.                      x = get_x(minx,col[row]);
  624.                      y = get_y(iy,row);
  625.                      clear_string(x,y,maxcol,maxx);
  626.                      put_string(&string[row][col[row]],x,y);
  627.                   }
  628.                }
  629.                else  /* can't wrap: shorten string */
  630.                {
  631.                   string[row][maxcol] = NULL;
  632.                   y = get_y(iy,row);
  633.                   clear_string(x,y,maxcol,maxx);
  634.                   put_string(&string[row][col[row]],x,y);
  635.                }
  636.  
  637.                if (col[row] < maxcol-1)
  638.                   col[row]++;
  639.                else if (row < bottom_row)
  640.                {
  641.                   row++;
  642.                   col[row] = 0;
  643.                   unblank(string[row]);
  644.                }
  645.  
  646.                x = get_x(minx,col[row]);
  647.                y = get_y(iy,row);
  648.                put_editor_cursor(x,y);
  649.             }
  650.             else /* row = bottom_row-1 */
  651.             {
  652.                string[row][maxcol] = NULL;
  653.                clear_string(x,y,maxcol,maxx);
  654.                y = get_y(iy,row);
  655.                put_string(&string[row][col[row]],x,y);
  656.                x = get_x(minx,col[row]);
  657.                y = get_y(iy,row);
  658.                put_editor_cursor(x,y);
  659.             }
  660.          }
  661.  
  662.          else  /* wrapping not necessary */
  663.  
  664.          {
  665.             x = get_x(minx,col[row]);
  666.             y = get_y(iy,row);
  667.             clear_string(x,y,maxcol,maxx);
  668.             put_string(&string[row][col[row]],x,y);
  669.  
  670.             end[row] = strlen(string[row]);
  671.  
  672.             if (col[row] <= end[row]+1 && col[row] < maxcol-1)
  673.                 col[row]++;
  674.             else if (row < bottom_row-1)
  675.             {
  676.                row++;
  677.                col[row] = l;
  678.             }
  679.             else
  680.             {
  681.                x = get_x(minx,col[row]);
  682.                y = get_y(iy,row);
  683.                string[row][maxcol] = NULL;
  684.                clear_string(x,y,maxcol,maxx);
  685.                put_string(&string[row][col[row]],x,y);
  686.             }
  687.             x = get_x(minx,col[row]);
  688.             y = get_y(iy,row);
  689.             put_editor_cursor(x,y);
  690.          }
  691.       }
  692.  
  693.       /* printable character -- overstrike mode */
  694.  
  695.       else if ((is_char(key) || key == SPACEBAR) && overstrike)
  696.       {
  697.          remove_editor_cursor(x,y);
  698.          string[row][col[row]] = key;
  699.          char_string[0] = key;
  700.          clear_string(x,y,1,maxx);
  701.          put_string(char_string,x,y);
  702.  
  703.          if (col[row] < maxcol-1)
  704.              col[row]++;
  705.  
  706.          /* trying to write a character past the end of a row, must wrap */
  707.  
  708.          else if (row < bottom_row-1)
  709.          {
  710.             b = last_blank(string[row])+1;
  711.             l = strlen(&string[row][b]);
  712.             unblank(string[row+1]);
  713.             if (can_wrap(&string[row][b],string[row+1],maxcol))
  714.             {
  715.                word_wrap(&string[row][b],string[row+1]);
  716.                string[row][b] = NULL;
  717.  
  718.                /* redraw the two rows of text */
  719.  
  720.                y = get_y(iy,row);
  721.                clear_string(minx,y,maxcol,maxx);
  722.                put_string(string[row],minx,y);
  723.  
  724.                row++;
  725.                unblank(string[row]);
  726.  
  727.                y = get_y(iy,row);
  728.                clear_string(minx,y,maxcol,maxx);
  729.                put_string(string[row],minx,y);
  730.  
  731.                col[row] = l;
  732.  
  733.             }
  734.             else
  735.             {
  736.                row++;
  737.                col[row] = 0;
  738.                unblank(string[row]);
  739.             }
  740.          }
  741.  
  742.          x = get_x(minx,col[row]);
  743.          y = get_y(iy,row);
  744.          put_editor_cursor(x,y);
  745.       }
  746.    }
  747.  
  748.    /* end while */
  749.  
  750.    l = 0;                       /* put all the strings in one array */
  751.    for (n = 0; n < nrows; n++)  /* separated by nulls */
  752.    {
  753.       strcpy(&array[l],string[n]);
  754.       l += strlen(string[n]) + 1;
  755.       free (string[n]);    /* free the temporary arrays */
  756.       array[l] = 0;
  757.       l++;
  758.    }
  759.  
  760.    *array_len = l;
  761.  
  762.    free(tempstring);
  763.    return(OK);
  764. }
  765.  
  766. /**********************************************************************\
  767. *                                                                      *
  768. *  end_paragraph -- find the first blank line after a line of text     *
  769. *                                                                      *
  770. \**********************************************************************/
  771.  
  772. end_paragraph(row,string)
  773. char *string[60];
  774. int row;
  775. {
  776.    register int n;
  777.  
  778.    for (n = row+1; n < 60; n++)
  779.    {
  780.       unblank(string[n]);
  781.       if (string[n][0] == NULL)
  782.          break;
  783.    }
  784.    n--;
  785.    return(n);
  786. }
  787.  
  788. /**********************************************************************\
  789. *                                                                      *
  790. * first_blank -- find the first blank space before the end of a string *
  791. *                                                                      *
  792. \**********************************************************************/
  793.  
  794. first_blank(s)
  795. char *s;
  796. {
  797.    register int i;
  798.    int nchar;
  799.  
  800.    nchar = strlen(s);
  801.  
  802.    i = 0;
  803.    while (i <= nchar && is_char(s[i]))
  804.        i++;
  805.  
  806.    /* return value of blank */
  807.  
  808.    return(i);
  809. }
  810.  
  811. /**********************************************************************\
  812. *                                                                      *
  813. *  get_x -- calculate the x position based on row and column           *
  814. *                                                                      *
  815. \**********************************************************************/
  816.  
  817. get_x(x,col)
  818. int x, col;
  819. {
  820.    return(x + col * CHAR_WIDTH);
  821. }
  822.  
  823. /**********************************************************************\
  824. *                                                                      *
  825. *  get_y -- calculate the y position based on row and column           *
  826. *                                                                      *
  827. \**********************************************************************/
  828.  
  829. get_y(y,row)
  830. int y, row;
  831. {
  832.    return(y + (row-top_row) * (ptsize+1));
  833. }
  834.  
  835. /**********************************************************************\
  836. *                                                                      *
  837. *  help_screen -- display keystroke help                               *
  838. *                                                                      *
  839. \**********************************************************************/
  840.  
  841. void help_screen()
  842. {
  843.    register int i;
  844.    unsigned char key, aux;
  845.  
  846.    static char string[13][50] = {
  847.    " Arrows: move the cursor around",
  848.    " Del:    delete a letter",
  849.    " Ctrl-Y: delete the whole line",
  850.    " Home:   go to beginning of line",
  851.    " End:    go to end of line",
  852.    " PgUp:   go up one screen",
  853.    " PgDn:   go down one screen",
  854.    " Enter:  go to the next line",
  855.    " Ins:    insert or overstrike" ,
  856.    " Esc:    done editing" ,
  857.    " "
  858.    "   press any key to exit help"
  859.    };
  860.  
  861.    static int line [] = {46,58,70,82,94,106,118,130,142,154,166,182};
  862.  
  863.    fg_save(10,309,25,189);
  864.  
  865.    background = 2;
  866.    fg_setcolor(2);
  867.    fg_rect(10,309,25,189);
  868.    fg_setcolor(15);
  869.    draw_box(11,308,26,188);
  870.  
  871.    for (i = 0; i < 12; i++)
  872.    {
  873.       put_string(string[i],14,line[i]);
  874.    }
  875.    fg_getkey(&key,&aux);
  876.    fg_restore(10,309,25,189);
  877.    background = 0;
  878. }
  879.  
  880. /**********************************************************************\
  881. *                                                                      *
  882. *  is_char -- is it a legitimate character that we can display?        *
  883. *                                                                      *
  884. \**********************************************************************/
  885.  
  886. is_char(c)
  887. char c;
  888. {
  889.    if (c > 32 && c <= 126)
  890.       return(TRUE);
  891.    else
  892.       return(FALSE);
  893. }
  894.  
  895. /**********************************************************************\
  896. *                                                                      *
  897. *  last_blank -- find the last blank space before the end of a string  *
  898. *                                                                      *
  899. \**********************************************************************/
  900.  
  901. last_blank(s)
  902. char *s;
  903. {
  904.    register int i;
  905.  
  906.    /* find the end of the string */
  907.  
  908.    for (i = 0; s[i]; i++)
  909.        ;
  910.  
  911.    /* count backwards, finding the blank */
  912.  
  913.    while (i > 0 && is_char(s[i-1]))
  914.        i--;
  915.  
  916.    i--;  /* next character back must be non-alpha */
  917.  
  918.    /* return value of blank */
  919.  
  920.    return(i);
  921. }
  922.  
  923. /**********************************************************************\
  924. *                                                                      *
  925. *  put_editor_cursor -- put a cursor under where the next char goes    *
  926. *                                                                      *
  927. \**********************************************************************/
  928.  
  929. void put_editor_cursor(x,y)
  930. int x, y;
  931. {
  932.    int color;
  933.  
  934.    color = fg_getcolor();
  935.  
  936.    if (mode06 || mode11)
  937.       fg_setcolor(1);
  938.    else if (overstrike)
  939.       fg_setcolor(2);
  940.    else
  941.       fg_setcolor(14);
  942.  
  943.    fg_move(x,y+1);
  944.    fg_draw(x+8,y+1);
  945.    fg_setcolor(color);
  946. }
  947.  
  948. /**********************************************************************\
  949. *                                                                      *
  950. *  remove_editor_cursor -- delete the cursor from its current position *
  951. *                                                                      *
  952. \**********************************************************************/
  953.  
  954. void remove_editor_cursor(x,y)
  955. int x, y;
  956. {
  957.    int color;
  958.  
  959.    color = fg_getcolor();
  960.    fg_setcolor(background);
  961.    fg_move(x,y+1);
  962.    fg_draw(x+8,y+1);
  963.    fg_setcolor(color);
  964. }
  965.  
  966. /**********************************************************************\
  967. *                                                                      *
  968. *  unblank -- remove trailing blanks and other garbage from a string   *
  969. *                                                                      *
  970. \**********************************************************************/
  971.  
  972. void unblank(s)
  973. char *s;
  974. {
  975.    register int i;
  976.  
  977.    /* find the end of the string */
  978.  
  979.    for (i = 0; s[i]; i++)
  980.        ;
  981.  
  982.    /* count back trailing spaces */
  983.  
  984.    while (i > 0 && !is_char(s[i-1]))
  985.        i--;
  986.  
  987.    /* set new end of string */
  988.  
  989.    s[i] = '\0';
  990. }
  991.  
  992. /**********************************************************************\
  993. *                                                                      *
  994. *  word_wrap -- take the last word of one string, put at beginning of  *
  995. *  next string.                                                        *
  996. *                                                                      *
  997. \**********************************************************************/
  998.  
  999. void word_wrap(s1,s2)
  1000. char *s1, *s2;
  1001. {
  1002.    char tempstring[60];
  1003.  
  1004.    strcpy(tempstring,s1);
  1005.    strcat(tempstring," ");
  1006.    strcat(tempstring,s2);
  1007.    strcpy(s2,tempstring);
  1008. }
  1009.